package com.cskaoyan.duolai.clean.housekeeping.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.duolai.clean.common.constants.ErrorInfo;
import com.cskaoyan.duolai.clean.common.expcetions.ForbiddenOperationException;
import com.cskaoyan.duolai.clean.common.model.dto.PageDTO;
import com.cskaoyan.duolai.clean.housekeeping.converter.RegionServeConverter;
import com.cskaoyan.duolai.clean.housekeeping.dto.*;
import com.cskaoyan.duolai.clean.housekeeping.enums.HousekeepingStatusEnum;
import com.cskaoyan.duolai.clean.housekeeping.dao.entity.*;
import com.cskaoyan.duolai.clean.housekeeping.dao.mapper.*;
import com.cskaoyan.duolai.clean.housekeeping.request.RegionServeCommand;
import com.cskaoyan.duolai.clean.housekeeping.request.ServePageRequest;
import com.cskaoyan.duolai.clean.housekeeping.service.IHomeService;
import com.cskaoyan.duolai.clean.housekeeping.service.IRegionServeService;
import com.cskaoyan.duolai.clean.housekeeping.service.IServeTypeService;
import com.cskaoyan.duolai.clean.mvc.utils.UserContext;
import com.cskaoyan.duolai.clean.mysql.utils.PageUtils;
import com.cskaoyan.duolai.clean.redis.constants.RedisConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务表 服务实现类
 * </p>
 */
@Service
public class RegionServeServiceImpl extends ServiceImpl<RegionServeMapper, RegionServeDO> implements IRegionServeService {

    @Resource
    RegionServeConverter regionServeConverter;

    @Resource
    ServeItemMapper serveItemMapper;

    @Resource
    RegionServeMapper regionServeMapper;

    @Resource
    RegionMapper regionMapper;
    @Resource
    ServeTypeMapper serveTypeMapper;

    @Resource
    ServeSyncMapper serveSyncMapper;

    @Resource
    IServeTypeService serveTypeService;

    @Resource
    IRegionServeService iRegionServeService;







    @Override
    public PageDTO<RegionServeDTO> getPage(ServePageRequest servePageQueryReqDTO) {
        Page<RegionServeDO> page = PageUtils.parsePageQuery(servePageQueryReqDTO, RegionServeDO.class);
        Page<RegionServeDO> regionServeDOPage = regionServeMapper.queryRegionServeListByRegionId(servePageQueryReqDTO.getRegionId(), page);
        List<RegionServeDTO> regionServeDTOS = regionServeConverter.regionServeDOsToRegionServeDTOs(regionServeDOPage.getRecords());

        return PageUtils.toPage(page, regionServeDTOS);
    }


    @Override

    public void batchAdd(List<RegionServeCommand> regionServeCommandList) {
        List<RegionServeDO> regionServeDOList = regionServeCommandList.stream()
                .map(item -> {
                    RegionDO regionDO = regionMapper.selectById(item.getRegionId());
                    RegionServeDO regionServeDO = regionServeConverter.regionServeCommand2DO(item);
                    regionServeDO.setCityCode(regionDO.getCityCode());
                    return regionServeDO;
                })
                .toList();
       saveBatch(regionServeDOList);
    }

    @Override
    @Caching(
            put = {@CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")},
            evict = {@CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#regionId")}
    )
    public RegionServeDetailDTO updatePrice(Long id, Long regionId, BigDecimal price) {
        Long currentUserId = UserContext.currentUserId();
        if (id<0||regionId<0||price.compareTo(BigDecimal.valueOf(0))<0)
        {
            throw new ForbiddenOperationException(ErrorInfo.Msg.REQUEST_PARAM_ILLEGAL);
        }
        RegionServeDO one = lambdaQuery().eq(RegionServeDO::getServeItemId, id).eq(RegionServeDO::getRegionId, regionId).one();
        if (one==null)
        {
            throw new ForbiddenOperationException("服务不存在");
        }
        LambdaUpdateWrapper<RegionServeDO> updatePrice = new LambdaUpdateWrapper<RegionServeDO>().eq(RegionServeDO::getId, id)
                .eq(RegionServeDO::getRegionId, regionId).set(RegionServeDO::getPrice, price).set(RegionServeDO::getUpdateBy,currentUserId);

        boolean update = iRegionServeService.update(updatePrice);
        if (!update)
        {
            throw new ForbiddenOperationException("修改失败");
        }
        RegionServeDetailDO regionServeDetail = regionServeMapper.findRegionServeDetail(one.getId());
        RegionServeSyncDO regionServeSyncDO = new RegionServeSyncDO();
        regionServeSyncDO.setId(id);
        regionServeSyncDO.setPrice(price);
        serveSyncMapper.updateById(regionServeSyncDO);
        return regionServeConverter.regionServeDetailDO2DTO(regionServeDetail);

    }

    @Override
    @CachePut(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#regionId")
    public List<RegionServeDetailDTO> changeHotStatus(Long id, Long regionId, Integer flag) {
        Long currentUserId = UserContext.currentUserId();
        if (id<0||regionId<0)
        {
            throw  new ForbiddenOperationException(ErrorInfo.Msg.REQUEST_PARAM_ILLEGAL);
        }

        RegionServeDO one = lambdaQuery().eq(RegionServeDO::getServeItemId, id).eq(RegionServeDO::getRegionId, regionId).one();
        if (one==null)
        {
            throw new ForbiddenOperationException("服务不存在");
        }
        LambdaUpdateWrapper<RegionServeDO> updateHot = new LambdaUpdateWrapper<RegionServeDO>().eq(RegionServeDO::getServeItemId, id)
                .eq(RegionServeDO::getRegionId, regionId).set(RegionServeDO::getIsHot, flag).set(RegionServeDO::getUpdateBy,currentUserId);
        boolean update = iRegionServeService.update(updateHot);
        if (!update)
        {
            throw new ForbiddenOperationException("修改失败");
        }
        List<RegionServeDetailDO> regionServeDetailByRegionId = regionServeMapper.findRegionServeDetailByRegionId(regionId);
        return regionServeConverter.regionServeDetailDOs2DTOs(regionServeDetailByRegionId);
    }

    @Override
    public int queryServeCountByRegionIdAndSaleStatus(Long regionId, Integer saleStatus) {
        LambdaQueryWrapper<RegionServeDO> queryWrapper = Wrappers.<RegionServeDO>lambdaQuery().eq(RegionServeDO::getRegionId, regionId)
                .eq(RegionServeDO::getSaleStatus, saleStatus);
        Long count = baseMapper.selectCount(queryWrapper);
        return Integer.parseInt(count.toString());
    }

    @Override
    public int queryServeCountByServeItemIdAndSaleStatus(Long serveItemId, Integer saleStatus) {
        LambdaQueryWrapper<RegionServeDO> queryWrapper = Wrappers.<RegionServeDO>lambdaQuery().eq(RegionServeDO::getServeItemId, serveItemId)
                .eq(RegionServeDO::getSaleStatus, saleStatus);
        Long count = baseMapper.selectCount(queryWrapper);
        return Integer.parseInt(count.toString());
    }

    @Override
    public void deleteById(Long id) {
        RegionServeDO regionServeDO = baseMapper.selectById(id);
        if (ObjectUtil.isNull(regionServeDO)){
            throw new ForbiddenOperationException("区域服务不存在");
        }

        if (HousekeepingStatusEnum.INIT.getStatus() != regionServeDO.getSaleStatus()) {
            throw new ForbiddenOperationException("草稿状态方可删除");
        }

        baseMapper.deleteById(id);

    }
    @Cacheable(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")
    @Override
    public RegionServeDetailDTO findDetailByIdCache(Long id) {
        RegionServeDetailDTO detailByIdDb = findDetailByIdDb(id);
        if (detailByIdDb == null) {
            return new RegionServeDetailDTO();
        }

        return detailByIdDb;

    }

    public RegionServeDetailDTO findDetailByIdDb(Long id) {
        System.out.println(" findDetailByIdDb" );

        if (id<0)
        {
            throw new ForbiddenOperationException(ErrorInfo.Msg.REQUEST_PARAM_ILLEGAL);
        }
        RegionServeDetailDO regionServeDetail = regionServeMapper.findRegionServeDetail(id);
        return  regionServeConverter.regionServeDetailDO2DTO(regionServeDetail);
    }

    @Autowired
    IHomeService iHomeService;

    @Override
    public List<ServeTypeHomeDTO> refreshFirstPageRegionServeList(Long regionId) {
        return iHomeService.queryServeIconCategoryByRegionIdDb(regionId);
    }

    @Override
    public List<RegionServeDetailDTO> refreshFistPageHotServeList(Long regionId) {
        return findHotServeListByRegionId(regionId);
    }

    @Override
    public List<DisplayServeTypeDTO> refreshFirstPageServeTypeList(Long regionId) {
        return iHomeService.queryServeTypeListByRegionIdDb(regionId);
    }

    @Override
    public List<RegionServeDetailDTO> findHotServeListByRegionId(Long regionId) {

        System.out.println("findHotServeListByRegionId");



        RegionDO regionDO = regionMapper.selectById(regionId);
        if (HousekeepingStatusEnum.DISABLE.getStatus() == regionDO.getActiveStatus()) {
            return Collections.emptyList();
        }


        // 2. 查询精选推荐列表
        List<RegionServeDetailDO> hotServeListByRegionId = regionServeMapper.findHotServeListByRegionId(regionId);


        return regionServeConverter.regionServeDetailDOs2DTOs(hotServeListByRegionId);
    }

    @Override
    public List<DisplayServeTypeDTO> findServeTypeListByRegionId(Long regionId) {
        // 1. 是否是已启用的区域
        RegionDO regionDO = regionMapper.selectById(regionId);
        if (HousekeepingStatusEnum.DISABLE.getStatus() == regionDO.getActiveStatus()) {
            return Collections.emptyList();
        }


        // 2. 查询区域下的类型信息
        List<ServeTypeDO> serveTypeListByRegionId = regionServeMapper.findServeTypeListByRegionId(regionId);

        if (serveTypeListByRegionId == null) {
            return Collections.emptyList();
        }
        return regionServeConverter.serveTypeDOsToFirstPageServeTypeDTOs(serveTypeListByRegionId);
    }

    @Override
    @Transactional
    @Caching(
            put = {@CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")},
            evict = {
                    @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_PARTIAL_SERVE_CACHE, key = "#result.regionId"),
                    @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#result.regionId"),
                    @CacheEvict(cacheNames = RedisConstants.CacheName.REGION_SERVE_TYPE, key = "#result.regionId")
            }
    )
    public RegionServeDetailDTO onSale(Long id) {
        RegionServeDO regionServeDO = baseMapper.selectById(id);

        System.out.println("regionServeDO = " + regionServeDO);

        //当且仅当服务项，服务类型，以及区域状态都为启用状态
        ServeItemDO serveItemDO = serveItemMapper.selectById(regionServeDO.getServeItemId());
        if (ObjectUtil.isNull(serveItemDO) || serveItemDO.getActiveStatus() != HousekeepingStatusEnum.ENABLE.getStatus()){
            throw new ForbiddenOperationException("服务项未启用");
        }

        ServeTypeDO serveTypeDO = serveTypeMapper.selectById(serveItemDO.getServeTypeId());
        if (ObjectUtil.isNull(serveTypeDO) || serveTypeDO.getActiveStatus() != HousekeepingStatusEnum.ENABLE.getStatus()){
            throw new ForbiddenOperationException("服务类型未启用");
        }

        RegionDO regionDO = regionMapper.selectById(regionServeDO.getRegionId());
        if (ObjectUtil.isNull(regionDO) || regionDO.getActiveStatus() != HousekeepingStatusEnum.ENABLE.getStatus()){
            throw new ForbiddenOperationException("该区域未启用");
        }

        //区域服务项为下架/草稿状态
        if (HousekeepingStatusEnum.INIT.getStatus() == regionServeDO.getSaleStatus()
        || HousekeepingStatusEnum.DISABLE.getStatus() == regionServeDO.getSaleStatus()){
            regionServeDO.setSaleStatus(HousekeepingStatusEnum.ENABLE.getStatus());
            updateById(regionServeDO);
        }


        addServeSync(id);

        return findDetailByIdDb(id);
    }

    private void addServeSync(Long serveId) {
        //服务信息
        RegionServeDO regionServe = baseMapper.selectById(serveId);
        //区域信息
        RegionDO region = regionMapper.selectById(regionServe.getRegionId());
        //服务项信息
        ServeItemDO serveItem = serveItemMapper.selectById(regionServe.getServeItemId());
        //服务类型
        ServeTypeDO serveType = serveTypeMapper.selectById(serveItem.getServeTypeId());

        RegionServeSyncDO regionServeSyncDO = regionServeConverter
                .regionServeToServeSyncDO(serveType, serveItem, regionServe, region.getCityCode());
        // 插入数据
        serveSyncMapper.insert(regionServeSyncDO);
    }



    @Override
    @Transactional
    @Caching(
            put = {@CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")},
            evict = {
                    @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_PARTIAL_SERVE_CACHE, key = "#result.regionId"),
                    @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#result.regionId"),
                    @CacheEvict(cacheNames = RedisConstants.CacheName.REGION_SERVE_TYPE, key = "#result.regionId")
            }
    )
    public RegionServeDTO offSale(Long id) {
        Long currentUserId = UserContext.currentUserId();
        if (id<0)
        {
            throw new ForbiddenOperationException(ErrorInfo.Msg.REQUEST_PARAM_ILLEGAL);
        }
        LambdaUpdateWrapper<RegionServeDO> set = new LambdaUpdateWrapper<RegionServeDO>().eq(RegionServeDO::getId, id)
                .set(RegionServeDO::getSaleStatus, 1).set(RegionServeDO::getUpdateBy,currentUserId);
        boolean update = iRegionServeService.update(set);
        if (!update)
        {
            throw new ForbiddenOperationException("修改失败");
        }
        serveSyncMapper.deleteById(id);
        RegionServeDO one = lambdaQuery().eq(RegionServeDO::getId, id).one();
        return regionServeConverter.regionServeDOToRegionServeDTO(one);

    }

    @Override
    public ServeDetailDTO findServeDetailById(Long id) {
        ServeDetailDO serveDetailById = regionServeMapper.findServeDetailById(id);
        return regionServeConverter.serveDetailDO2DTO(serveDetailById);

    }
}
